import inspect
from functools import wraps
from typing import Any, Callable
from sqlalchemy.ext.asyncio import AsyncSession
from core.user_context import get_user_context
from .engine import apply_permission


def with_permission(table_name: str) -> Callable:
    """
    数据权限装饰器，根据指定的表名应用数据权限。

    :param table_name: 需要应用权限控制的数据库表名。
    """
    def decorator(func: Callable) -> Callable:
        @wraps(func)
        async def wrapper(*args, **kwargs) -> Any:
            # 从参数中查找数据库会话实例
            db = next((arg for arg in args if isinstance(arg, AsyncSession)), None)
            
            if not db:
                # 如果没有找到db session，直接执行原函数
                return await func(*args, **kwargs)
                    
            # 获取当前请求的用户上下文
            user_context = get_user_context()
            if not user_context:
                # 如果没有用户上下文，直接执行原函数
                return await func(*args, **kwargs)
            
            # 应用数据权限
            try:
                # 调用权限引擎获取SQL查询条件
                permission_condition = await apply_permission(db, table_name, user_context)

                # 检查目标函数签名，决定如何传递权限条件
                sig = inspect.signature(func)
                if 'permission_condition' in sig.parameters:
                    # 如果函数签名中有 `permission_condition` 参数，则通过关键字参数传递
                    kwargs['permission_condition'] = permission_condition
                else:
                    # 否则，为了向后兼容，仍然注入到kwargs中（如果原始调用者使用了**kwargs）
                    # 这部分逻辑可以根据实际情况简化，如果所有服务都重构了，就可以去掉
                    kwargs['permission_condition'] = permission_condition

            except Exception as e:
                # 在生产环境中，这里应该记录详细的错误日志
                # 为了安全起见，如果权限引擎出错，默认不允许访问任何数据
                # 注意：'1=0' 是一个安全的默认值，它会导致查询返回空结果
                kwargs['permission_condition'] = "1=0"

            # 执行原函数
            return await func(*args, **kwargs)
        
        return wrapper
    return decorator
